package middleware

import (
	"bytes"
	"encoding/json"
	"gitee.com/xluomo945/fm/log"
	"github.com/gin-gonic/gin"
	"io"
	"net/http"
	"time"
)

type response struct {
	gin.ResponseWriter
	buf *bytes.Buffer
}

func (r response) Write(data []byte) (int, error) {
	_, _ = r.buf.Write(data)
	return r.ResponseWriter.Write(data)
}

func DataFlow(ctx *gin.Context) {
	start := time.Now()
	log.Info(ctx, "start time: %s", start.Format("2006-01-02 15:04:05"))
	log.Info(ctx, "route: %s", ctx.FullPath())
	log.Info(ctx, "url: %s", ctx.Request.URL.RequestURI())
	log.Info(ctx, "method: %s", ctx.Request.Method)
	log.Info(ctx, "header: %v", header(ctx.Request.Header))
	log.Info(ctx, "data: %s", data(ctx))

	writer := &response{buf: &bytes.Buffer{}, ResponseWriter: ctx.Writer}
	ctx.Writer = writer
	ctx.Next()

	end := time.Now()
	log.Info(ctx, "http code: %d", writer.Status())
	log.Info(ctx, "response: %s", writer.buf.String())
	log.Info(ctx, "end time: %s", end.Format("2006-01-02 15:04:05"))
	log.Info(ctx, "use time: %s", end.Sub(start).String())
}

type request struct {
	Query map[string][]string `json:"query"`
	Body  map[string]any      `json:"body"`
	Uri   map[string][]string `json:"uri"`
}

func data(ctx *gin.Context) string {
	body := &request{
		Query: make(map[string][]string),
		Body:  make(map[string]any),
		Uri:   make(map[string][]string),
	}
	_ = ctx.ShouldBindQuery(&body.Query)
	_ = ctx.ShouldBindJSON(&body.Body)
	_ = ctx.ShouldBindUri(&body.Uri)

	// 这里需要把Body参数重新填回去, 上下文里面的参数只能被读一次
	j, _ := json.Marshal(body.Body)
	ctx.Request.Body = io.NopCloser(bytes.NewReader(j))

	str, _ := json.Marshal(body)
	return string(str)
}

func header(header http.Header) string {
	str, _ := json.Marshal(header)
	return string(str)
}
